#include "ui_sprite.h"

CUISprite::CUISprite(CTexture *pTexture) :
    m_pTexture(pTexture),
    m_fRotation(0.0f),
    m_pSprite(nullptr),
    m_fScaleX(1.0f),
    m_fScaleY(1.0f)
{
    /**
     * Constructor, ensure that we save the texture's instance and initialise
     * the sprite.
     *
     * @param CTexture *pTexture The texture to use.
     */
    setTexture(pTexture);

    D3DXCreateSprite(CDeviceManager::getInstance()->getDevice(), &m_pSprite);
}

CUISprite::CUISprite(const string &szTextureName)
    : m_pTexture(nullptr),
    m_fRotation(0.0f),
    m_pSprite(nullptr),
    m_fScaleX(1.0f),
    m_fScaleY(1.0f)
{
    /**
     * @param const string &szTextureName The name of the texture to use
     */
    setTexture(szTextureName);
    
    D3DXCreateSprite(CDeviceManager::getInstance()->getDevice(), &m_pSprite);
}

CUISprite::~CUISprite()
{
    /**
     * Release the sprite.
     */
    m_pSprite->Release();
}


void CUISprite::setRotation(float fAngle)
{
    /**
     * @param float fAngle The angle rotation of the sprite (in radians)
     */
    m_fRotation = fAngle;
}

void CUISprite::setRotationDegrees(float fAngle)
{
    /**
     * @param float fAngle The angle rotation of the sprite (in degrees)
     */
    m_fRotation = fAngle / 180.0f * static_cast<float>(Constants::PI);
}

float CUISprite::getRotation() const
{
    /**
     * @return float The angle rotation of the sprite (in radians)
     */
    return m_fRotation;
}

float CUISprite::getRotationDegrees() const
{
    /**
     * @return float The angle rotation of the sprite (in degrees)
     */
    return m_fRotation / static_cast<float>(Constants::PI) * 180.0f;
}

void CUISprite::render()
{
    /**
     * Draws the sprite on the screen.
     */
    if (isVisible())
    {
        m_pSprite->Begin(D3DXSPRITE_ALPHABLEND);
        D3DXMATRIX matTransformation;

        D3DXVECTOR3 vecPosition(getPositionLeft(), getPositionTop(), 0.0f);

        D3DXVECTOR2 vecScale = D3DXVECTOR2(getScaleX(), getScaleY());
        D3DXVECTOR2 vecCenter = D3DXVECTOR2(getPositionLeft() + getWidth() / 2, 
            getPositionTop() + getHeight() / 2);
        D3DXVECTOR3 vecCenter3 = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

        D3DXMatrixTransformation2D(&matTransformation, &vecCenter, 0.0, 
            &vecScale, &vecCenter, m_fRotation, NULL);
        m_pSprite->SetTransform(&matTransformation);

        m_pSprite->Draw(m_pTexture->getTexture(), nullptr, 
                        &vecCenter3, &vecPosition, 
                        D3DCOLOR_XRGB(255, 255, 255));

        m_pSprite->End();
    }
    renderChildren();
}

void CUISprite::setScale(float fScaleX, float fScaleY)
{
    /**
     * @param float fScaleX The new X Scale of the texture
     * @param float fScaleY The new Y scale of the texture
     */
    m_fScaleX = fScaleX;
    m_fScaleY = fScaleY;
}

float CUISprite::getScaleX() const
{
    /**
     * @return float The X scale of the sprite
     */
    return m_fScaleX;
}

float CUISprite::getScaleY() const
{
    /**
     * @return float The Y scale of the sprite
     */
    return m_fScaleY;
}

LPD3DXSPRITE CUISprite::getSprite() const
{
    /**
     * @return The DirectX Sprite object
     */
    return m_pSprite;
}

void CUISprite::setTexture(const string &szTextureName)
{
    /**
     * Reassigns the sprite to draw a new texture. This updates the size
     * properties of this UI to the size of the texture as well.
     *
     * @param const string &szTextureName The name of the texture
     */
    CTextureContainer *pTextures(CTextureContainer::getInstance());
    CTexture *pTexture(pTextures->getTexture(szTextureName));
    if (pTexture == nullptr)
    {
        pTexture = pTextures->addTexture(szTextureName, szTextureName, 
            CDeviceManager::getInstance()->getDevice());
    }
    
    setTexture(pTexture);   
}

void CUISprite::setTexture(CTexture *pTexture)
{
    /**
     * Reassigns the sprite to draw a new texture. This updates the size
     * properties of this UI to the size of the texture as well.
     *
     * @param CTexture *pTexture The new texture to render
     */
    m_pTexture = pTexture;

    setHeight(static_cast<float>(pTexture->getHeight()));
    setWidth(static_cast<float>(pTexture->getWidth()));

    pTexture->setPermanent(true);
}

CTexture *CUISprite::getTexture() const
{
    /**
     * @return CTexture* The current texture used by this sprite
     */
    return m_pTexture;
}